using System;
using System.Collections.Generic;
using System.Text;
using RideMe.Core.Properties;
using System.Drawing;
using System.Runtime.Serialization;
using System.IO;

namespace RideMe.Core
{
    [Serializable()]
    public class Options : IDisposable 
    {

        private Options()
        {
        }

        private static readonly object _padlock = new object();
        private static Options _instance;

        /// <summary>
        /// Gets the instance of this singelton object. If the
        /// object isn't instantiated it, tries to get the options
        /// that may have been previously saved.
        /// </summary>
        /// <value>The instance.</value>
        public static Options Instance
        {
            get
            {
                lock (_padlock)
                {
                    if (_instance == null)
                    {
                        // Deserialize options.
                        _instance = GetOptions();

                        // If it's still null, new-up an instance.
                        if (_instance == null)
                        {
                            _instance = new Options();
                        }
                    }
                }
                return _instance;
            }
        }

        [NonSerialized]
        EventHandler _nonSerializableHandlers;
        EventHandler _serializableHandlers;

        /// <summary>
        /// Declares a serialization-safe OptionsChanged event. If 
        /// we don't do this, it tries to serialize the freakin'
        /// subscriber(DocumentExplorer control).
        /// </summary>
        public event EventHandler OptionsChanged
        {
            add
            {
                if (value.Target.GetType().IsSerializable)
                {
                    _serializableHandlers =
                       (EventHandler)Delegate.Combine(_serializableHandlers, value);
                }
                else
                {
                    _nonSerializableHandlers =
                       (EventHandler)Delegate.Combine(_nonSerializableHandlers, value);
                }
            }

            remove
            {
                if (value.Target.GetType().IsSerializable)
                {
                    _serializableHandlers =
                      (EventHandler)Delegate.Remove(_serializableHandlers, value);
                }
                else
                {
                    _nonSerializableHandlers =
                      (EventHandler)Delegate.Remove(_nonSerializableHandlers, value);
                }
            }
        }

        /// <summary>
        /// Call this method to raise the options Changed event.
        /// </summary>
        protected virtual void OnOptionsChanged()
        {
            if (_nonSerializableHandlers != null)
            {
                _nonSerializableHandlers(this, EventArgs.Empty);
            }
            if (_serializableHandlers != null)
            {
                _serializableHandlers(this, EventArgs.Empty);
            }
        }

		private bool _launchInternalBrowser;
		/// <summary>
		/// Gets or sets the option to use the internal IE browser instead of the default browser on the system.
		/// </summary>
		/// <value>
		/// 	<c>true</c> to use the embedded browser; otherwise, <c>false</c>.
		/// </value>
		public bool LaunchInternalBrowser
		{
			get { return _launchInternalBrowser; }
			set { _launchInternalBrowser = value; }
		}


		private bool _convertTabsToSpaces = true;

		/// <summary>
		/// Gets or sets the option to use the internal IE browser instead of the default browser on the system.
		/// </summary>
		/// <value>
		/// 	<c>true</c> to use the embedded browser; otherwise, <c>false</c>.
		/// </value>
		public bool ConvertTabsToSpaces
		{
			get { return _convertTabsToSpaces; }
			set { _convertTabsToSpaces = value; }
		}

        [NonSerialized]
        private bool _suppressChangedEvent;

        public bool SuppressChangeEvent
        {
            get { return _suppressChangedEvent; }
            set { _suppressChangedEvent = value; }
        }
	

		private bool _runServer = true;

		/// <summary>
		/// Gets or sets the option to use the internal IE browser instead of the default browser on the system.
		/// </summary>
		/// <value>
		/// 	<c>true</c> to use the embedded browser; otherwise, <c>false</c>.
		/// </value>
		public bool RunServer
		{
			get { return _runServer; }
			set { _runServer = value; }
		}

        private bool _loadLastProjectAtStartUp;

        /// <summary>
        /// Gets or sets the option to Load the last project when the IDE starts.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if [load last project at start UP]; otherwise, <c>false</c>.
        /// </value>
        public bool LoadLastProjectAtStartUp
        {
            get { return _loadLastProjectAtStartUp; }
            set { _loadLastProjectAtStartUp = value; }
        }

        // Default Ruby path.
        private string _rubyPath = Resources.DefaultRubyPath;

        /// <summary>
        /// Gets or sets the ruby path.
        /// </summary>
        /// <value>The ruby path.</value>
        public string RubyPath
        {
            get { return _rubyPath; }
            set { _rubyPath = value; }
        }

        // Default
        private int _serverPort = 3000;

        /// <summary>
        /// Gets or sets the server port.
        /// </summary>
        /// <value>The server port.</value>
        public int ServerPort
        {
            get { return _serverPort; }
            set { _serverPort = value; }
        }

        private bool _showLineNumbers;

        /// <summary>
        /// Gets or sets the option to whether or not to show line numbers.
        /// </summary>
        /// <value><c>true</c> if [show line numbers]; otherwise, <c>false</c>.</value>
        public bool ShowLineNumbers
        {
            get { return _showLineNumbers; }
            set { _showLineNumbers = value;}
        }

        private Font _editorFont = new Font("Courier New", 10.0f);

        /// <summary>
        /// Gets or sets the editor font.
        /// </summary>
        /// <value>The editor font.</value>
        public Font EditorFont
        {
            get { return _editorFont; }
            set {_editorFont = value; }
        }

        private LineEndingStyle _lineEndings = LineEndingStyle.Windows;

        /// <summary>
        /// Gets or sets the LineEndingStyle.
        /// </summary>
        public LineEndingStyle LineEndings
        {
            get { return _lineEndings; }
            set { _lineEndings = value; }
        }

        private bool _showAllFiles = true;

        /// <summary>
        /// Gets or sets the option to show all files.
        /// /// </summary>
        public bool ShowAllFiles
        {
            get { return _showAllFiles; }
            set { _showAllFiles = value; }
        }

        private bool _loadLastProjectOnStartup;

        /// <summary>
        /// Gets or sets the option to load the last project on startup.
        /// </summary>
        public bool LoadLastProjectOnStartup
        {
            get { return _loadLastProjectOnStartup; }
            set { _loadLastProjectOnStartup = value; }
        }

        private string _lastLoadedProjectPath;

        /// <summary>
        /// Gets or sets the value of the last loaded project path.
        /// </summary>
        public string LastLoadedProjectPath
        {
            get { return _lastLoadedProjectPath; }
            set { _lastLoadedProjectPath = value; }
        }

        private List<string> _previouslyOpenedFiles;

        /// <summary>
        /// Gets or sets the files that are open before the app closes.
        /// </summary>
        /// <value>The previously opened files.</value>
        public List<string> PreviouslyOpenedFiles
        {
            get { return _previouslyOpenedFiles; }
            set { _previouslyOpenedFiles = value; }
        }

        private bool _enableFolding = true;

        public bool EnableFolding
        {
            get { return _enableFolding; }
            set { _enableFolding = value; }
        }

        private string _lastProjectCreationLocation;

        public string LastProjectCreationLocation
        {
            get { return _lastProjectCreationLocation; }
            set { _lastProjectCreationLocation = value; }
        }

        private string _lastProjectOpenedLocation;

        public string LastProjectOpenedLocation
        {
            get { return _lastProjectOpenedLocation; }
            set { _lastProjectOpenedLocation = value; }
        }

        private Color _viewColor;

        public Color ViewColor
        {
            get 
            {
                if (_viewColor.Name == "0")
                {
                    _viewColor = SystemColors.Control;
                }
                return _viewColor; 
            }
            set { _viewColor = value; }
        }

        private Color _modelColor;

        public Color ModelColor
        {
            get 
            {
                if (_modelColor.Name == "0")
                {
                    _modelColor = SystemColors.Control;
                }
                return _modelColor; 
            }
            set { _modelColor = value; }
        }

        private Color _controllerColor;

        public Color ControllerColor
        {
            get 
            {
                if (_controllerColor.Name == "0")
                {
                    _controllerColor = SystemColors.Control;
                }
                return _controllerColor; 
            }
            set { _controllerColor = value; }
        }

        private Color _testsColor;

        public Color TestsColor
        {
            get
            {
                if (_testsColor.Name == "0")
                {
                    _testsColor = SystemColors.Control;
                }
                return _testsColor;
            }
            set { _testsColor = value; }
        }

        private bool _showSpaces;

        public bool ShowSpaces
        {
            get { return _showSpaces; }
            set { _showSpaces = value; }
        }

        private bool _showTabs;

        public bool ShowTabs
        {
            get { return _showTabs; }
            set { _showTabs = value; }
        }

        private bool _showEol;

        public bool ShowEOL
        {
            get { return _showEol; }
            set { _showEol = value; }
        }
	
	
	

        /// <summary>
        /// Gets the options that may have been previously
        /// saved on disk in binary format.
        /// </summary>
        /// <returns></returns>
        private static Options GetOptions()
        {
            return (Options)SerializationService.DeserializeObject(Resources.OptionsFile);
        }

        /// <summary>
        /// Saves the options to disk in binary fomrat.
        /// </summary>
        /// <param name="options">The options.</param>
        public void SaveOptions(Options options)
        {
            SerializationService.SerializeObject(Resources.OptionsFile, options);
            if (!_suppressChangedEvent)
            {
                OnOptionsChanged();
            }
        }

        ~Options()
		{
			Dispose(false);
		}

		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
                _editorFont.Dispose();
			}
		}    
    }
}
